---@class ItemFlyMgr
ItemFlyMgr = {}
local this = ItemFlyMgr

function ItemFlyMgr.init()
    ---@type GComponent[]
    this.cacheList = {}
    ---@type GComponent[]
    this.itemList = {}
    this.poolRoot = nil
    this.diamondPos = Vector3.New()
    this.moneyPos = Vector3.New()
    this.bagPos = Vector3.New()
    this.teamExpPos = Vector3.New()
    this.flyRoot = nil
end
function ItemFlyMgr.SetDiamondPos(x,y)
    this.diamondPos:Set(x,y)
end
function ItemFlyMgr.SetMoneyPos(x,y)
    this.moneyPos:Set(x,y)
end
function ItemFlyMgr.SetBagPos(x,y)
    this.bagPos:Set(x,y)
end
function ItemFlyMgr.SetTeamExpPos(x,y)
    this.teamExpPos:Set(x,y)
end
function ItemFlyMgr.SetFlyRoot(root)
    this.flyRoot = root
end

--有正在飞行的obj
function ItemFlyMgr.HasFlyingObj()
    return table.getn(this.itemList) > 0
end
function ItemFlyMgr.OnDestroy()
    for k,v in pairs(this.cacheList) do
        v:Dispose()
    end
    for k,v in pairs(this.itemList) do
        v:Dispose()
    end
    if this.poolRoot then
        this.poolRoot:Dispose()
    end
    this.poolRoot = nil
    this.cacheList = {}
    this.itemList = {}
end
---@private
function ItemFlyMgr.GetFromPool()
    local item
    if #this.cacheList > 0 then
        item = table.remove(this.cacheList)
    else
        item = newGComponent("wardicon","UIFuncMenu")
    end
    this.itemList[item.id] = item
    return item
end
---@private
function ItemFlyMgr.ReturnToPool(item)
    if HelperFunc.IsNull(item) then
        return
    end
    this.itemList[item.id] = nil
    table.insert(this.cacheList,item)
    if not this.poolRoot then
        this.poolRoot = GComponent.New()
        this.poolRoot.displayObject.gameObject.name = "pool"
        this.poolRoot.visible = false
        GRoot.inst:AddChild(this.poolRoot)
    end
    this.poolRoot:AddChild(item)
end
--通用飞 UIHeadMenu UIFuncMenu对应位置
---@param rewards {itemModelId:any}
function ItemFlyMgr.FlyRewards(rewards,startPos)
    if not this.flyRoot then return end
    for k,v in pairs(rewards) do
        if v.itemModelId == CurrencyEnum.MONEY or
                v.itemModelId == CurrencyEnum.GOLD or
                v.itemModelId == CurrencyEnum.RoleExp then
            this.FlyDiamond(v.itemModelId,startPos)
        else
            this.FlyBag(v.itemModelId,startPos,k*0.1)
        end
    end
end
--飞到UIHeadMenu上对应资源位置
function ItemFlyMgr.FlyDiamond(itemID,startPos)
    if not this.flyRoot then return end
    local endPos = Vector3.New()
    itemID = tonumber(itemID)
    if itemID == CurrencyEnum.MONEY then
        endPos:SetV(this.moneyPos)
    elseif itemID == CurrencyEnum.GOLD then
        endPos:SetV(this.diamondPos)
    elseif itemID == CurrencyEnum.RoleExp then
        endPos:SetV(this.teamExpPos)
    else
        return
    end
    local createNum = 13    --创建数量
    local _interval = 0.05  --延时
    local width = 80  --随机起始点范围
    local height = 50--随机起始点范围
    local scaleTime = 0.1   --粒子大小缩放时间
    local scale = 0.5   --粒子缩放大小
    local speedCtrl = 2 -- 先慢后快>1  先快后慢<1
    for i = 0,createNum-1 do
        local x = startPos.x + math.random(-width,width)
        local y = startPos.y + math.random(-height,height)
        local speed = math.random(800,1580)  --粒子飞行速度取值范围
        --控制点
        local ctrlPos = Vector3.GetCacheVec()
        local random = math.random(1,100)   --方向控制
        local random2 = math.random(100,300)  -- x方向
        if random >= 30 then    --0全部向左边，100全部向右
            ctrlPos.x = startPos.x - random2
        else
            ctrlPos.x = startPos.x + random2
        end
        ctrlPos.y = startPos.y + (endPos.y-startPos.y)/4--y方向

        local item = this.FlyByBezier(itemID,this.flyRoot,x,y,endPos,_interval,nil,speed,ctrlPos,speedCtrl)
        item.scaleX = 0
        item.scaleY = 0
        item:TweenScale(Vector2(scale,scale),scaleTime)
        item:GetChild("quality").visible = false
        item:GetChild("frame").visible = false
    end
    utimer.timeCall(function ()
        AudioManager.TryPlayFlySound(itemID,true)
    end , _interval*1000, createNum)
end
--飞到UIFuncMenu 的背包
function ItemFlyMgr.FlyBag(itemID,startPos,delay)
    if not this.flyRoot then return end
    local endPos = Vector3.New()
    endPos:SetV(this.bagPos)
    local x = startPos.x + math.random(-60,60)
    local y = startPos.y + math.random(-60,60)
    itemID = tonumber(itemID)
    this.FlyByBezier(itemID,this.flyRoot,x,y,endPos,delay,this.FlyBagCallback)
    utimer.timeCall(function ()
        AudioManager.TryPlayFlySound(itemID,true)
    end , delay*1000, 1)
end
---@private
function ItemFlyMgr.FlyBagCallback()
    FireEvent(Config.EventType.FlyBagTransition)
end

function ItemFlyMgr.FlyByRandom(itemID, parentRoot,startPos,endPos,transition,timeFactor,delay)
    local pos = TablePool.Get()
    pos.x = startPos.x + math.random(-60,60)
    pos.y = startPos.y + math.random(-60,60)
    local item = this.Fly(itemID,parentRoot,pos,endPos,transition,timeFactor,delay)
    TablePool.Release(pos)
    return item
end
function ItemFlyMgr.GetRandomCtrlPoint(startX,startY,endX,endY)
    --随便取个控制点
    local x = 0
    local y = 0
    local random = math.random(1,100)
    local random2 = math.random(0.7,4)
    if random >= 50 then
        x = startX - (endX-startX)/random2
    else
        x = startX + (endX-startX)/random2
    end
    y = startY + (endY-startY)/4
    return x,y
end
function ItemFlyMgr.FlyByBezier(itemID, parentRoot,x,y,endPos,delay,callback,speed,ctrlPos,acc)
    local pos = TablePool.Get()
    pos.x = x
    pos.y = y
    local item = this.GetItemGo(itemID, parentRoot,pos)
    local dx = pos.x-endPos.x
    local dy = pos.y- endPos.y
    local dis = math.sqrt(dx * dx + dy * dy)
    speed = speed or 1580
    local time = dis / speed
    delay = delay or 0
    if not ctrlPos then
        pos.x,pos.y = this.GetRandomCtrlPoint(x,y,endPos.x,endPos.y)
    else
        pos.x = ctrlPos.x
        pos.y = ctrlPos.y
    end
    acc = acc or 1
    this.TweenBezier(item,endPos,pos, time,acc,delay,callback,true)
    TablePool.Release(pos)
    utimer.timeCall(function ()
        AudioManager.TryPlayFlySound(itemID,false)
    end , (time + delay)*1000, 1)
    return item
end
---@param go GObject
function ItemFlyMgr.FlyByBezier2(go,startPos,endPos,delay,time,callback)
    if not go then return end
    go:SetXY(startPos.x,startPos.y)
    local pos = Vector3.GetCacheVec()
    pos:SetV(startPos)
    delay = delay or 0
    --随便取个控制点
    local random = math.random(1,100)
    local random2 = math.random(0.7,4)
    if random >= 50 then
        pos.x = pos.x - (endPos.x-pos.x)/random2
    else
        pos.x = pos.x + (endPos.x-pos.x)/random2
    end

    pos.y = pos.y + (endPos.y-pos.y)/4
    this.TweenBezier(go,endPos,pos, time,1,delay,callback)
    Vector3.ReturnToPool(pos)
    return go
end
function ItemFlyMgr.Fly(itemID, parentRoot,startPos,endPos,transition,timeFactor,delay)
    local item = this.GetItemGo(itemID, parentRoot,startPos)
    timeFactor = timeFactor or 1
    local dx = startPos.x-endPos.x
    local dy = startPos.y- endPos.y
    local dis = math.sqrt(dx * dx + dy * dy)
    local time = dis / 1500 * timeFactor
    delay = delay or 0
    this.TweenMove(item,endPos,time,delay,transition)

    if delay > 0 then
        utimer.timeCall(function ()
            AudioManager.TryPlayFlySound(itemID,true)
        end , delay*1000, 1)
    else
        AudioManager.TryPlayFlySound(itemID,true)
    end
    
    utimer.timeCall(function ()
        AudioManager.TryPlayFlySound(itemID,false)
    end , (time+delay)*1000, 1)
    return item
end
---@private
function ItemFlyMgr.GetItemGo(itemID, parentRoot,startPos)
    local cfg,type,icon,scriptId,quality
    if logicMgr.ItemManager.IsEquip(itemID) then
        cfg = dataTable.getRow("t_equip", itemID)
        type = EnumConst.ItemTableEnum.Equip
        icon = cfg.f_EquipSuitlcon
        quality = cfg.f_EquipQuality
    else
        cfg = dataTable.getRow("t_item", itemID)
        if cfg then
            type = cfg.f_BagType
            icon = cfg.f_Icon
            scriptId = cfg.f_ScriptId
            quality = cfg.f_Quality
        end
    end
    if not cfg then return end
    local item = this.GetFromPool()
    local iconGo = item:GetChild("icon")
    local qualityGo = item:GetChild("quality")
    local frameGo = item:GetChild("frame")
    item.scaleX = 1
    item.scaleY = 1
    qualityGo.visible = true
    frameGo.visible = true
    UIComponentInterface:SetItemAllById(iconGo,qualityGo,frameGo,itemID)
    parentRoot:AddChild(item);
    item:SetPosition(startPos.x,startPos.y, 0)
    return item
end
---@private
function ItemFlyMgr.TweenMove(itemGo,endPos,time,delay,transition)
    local move = itemGo:TweenMove(endPos.x,endPos.y,time):SetDelay(delay) :OnComplete(function ()
        if not HelperFunc.IsNull(transition) then
            transition:Play()
        end
        this.ReturnToPool(itemGo)

    end);
    move:SetEase(EaseType.Linear);
end
---@private
function ItemFlyMgr.TweenBezier(itemGo,endPos,ctrl1Pos,time,acc,delay,callback,returnToPool)
    BezierTweenMgr.Create(itemGo,endPos,ctrl1Pos,time):SetDelay(delay):SetAccelerate(acc) :OnComplete(function()
        if returnToPool then
            this.ReturnToPool(itemGo)
        end
        if callback then
            callback()
        end
    end)
end
return ItemFlyMgr